// 负责数据劫持
// 把$data中的属性转换成getter/setter
class Observer {
  constructor (data) {
    this.walk(data)
  }
  // 遍历data属性
  walk (data) {
    // 1. data 为空 或者 不是对象的情况
    if ( !data || typeof data !== 'object') {
      return
    }
    // 2. 遍历data 属性
    Object.keys(data).forEach(key => {
      this.defineReactive(data, key, data[key])
    })
  }
  // 定义响应式
  // 使用 val 的原因
  // 1. 避免发生死递归  Observer.js:26 Uncaught RangeError: Maximum call stack size exceeded
  // 2. 在 get 中产生 了闭包，扩展了val
  defineReactive (obj, key, val) {
    const that = this
    // 将data 中的属性是对象的转换成响应式
    this.walk(val)
    // 依赖收集对象
    const dep = new Dep()
    Object.defineProperty(obj, key, {
      enumerable: true,
      configurable: true,
      get () {
        // 当前的属性有Watcher观察者对象时，Dep对其进行依赖收集
        Dep.target && dep.addSub(Dep.target)
        // 这种写法会与_proxyData 的get 方法发生死递归
        // return obj[key] 
        return val
      },
      set (newVal) {
        if (newVal === val) {
          return
        }
        val = newVal
        // 新设置的值是对象的进行响应式
        // this 指向 data
        that.walk(newVal)
        // 通知更新
        dep.notify()
      }
    })
  }
}